'''
Created on 26/10/2009

@author: eh01
'''
from ConfigParser import RawConfigParser
from Queue import Queue
from datastore import database
from datastore.database import DataStore
from datastore.resource import Resource
from reference.notificationtask import NotificationTask
from runtime import rt
from runtime.spaces import Spaces, SpacesContext
from runtime.task import Task
from spear.a2atask import A2ATask
from spear.wsdl import WSDL
from services.timetask import TimeTask
import logging
import os
import threading
import time
import unittest

LOGGING = logging.INFO

class NotificationTaskTest(unittest.TestCase):


    def setUp(self):
        queue = Queue()
        self.spaces = Spaces()
        spaces_context = SpacesContext(self.spaces, queue)
        runtime = rt.Runtime()
        runtime.initialise_spaces_with_local_config_files(spaces_context)       

        self.temp_database_name = 'test.db'
        self.original_database_name = database.DATABASE_NAME
        database.DATABASE_NAME = self.temp_database_name
        
        section = 'a2a data'
        self.cp = RawConfigParser()
        # the code coverage test does some magic when executing. And the properties_file_path has to be change to use the one below
        # which only just specifies the file name
#        properties_file_path = '../spear/a2a.properties'
        properties_file_path = os.path.dirname(__file__) + '/../spear/a2a.properties'
        self.cp.read(properties_file_path)
        self.client_cert_file_name = self.cp.get(section, 'clientcertfilename')
        self.client_cert_password = self.cp.get(section, 'clientcertpassword')
        self.spear_user_username = self.cp.get(section, 'spearuserusername')
        self.spear_user_password = self.cp.get(section, 'spearuserpassword')
        self.spear_user_remote_user = self.cp.get(section, 'spearuserremoteuser')
        self.spear_user_access_level = self.cp.get(section, 'spearuseraccesslevel')
        self.wsdl_path = self.cp.get(section, 'wsdlpath')

    def tearDown(self):
        try:
            os.remove(self.temp_database_name)
        except:
            pass


    def test_notification_monitoring(self):
        '''[NotificationTask] test notificaiton monitoring'''
        queue = Queue()
        spaces_context = SpacesContext(self.spaces, queue)        
        uri_reference = self.spaces.uri('reference:')
        uri_tasks = self.spaces.uri('tasks:')
        uri_spear = self.spaces.uri('spear:')
        uri_datastore = self.spaces.uri('datastore:')
        content_as_string = open(self.client_cert_file_name, 'rb').read()
        client_cert = Resource()
        client_cert.content = content_as_string
        client_cert.set_metadata(uri_datastore.resource.type, uri_spear.type.client_cert)
        client_cert.set_metadata(uri_spear.cert.password, self.client_cert_password)      
        access_token = Resource()
        access_token.spear_user_access_level = self.spear_user_access_level
        access_token.spear_user_username = self.spear_user_username
        access_token.spear_user_password = self.spear_user_password
        access_token.spear_user_remote_user = self.spear_user_remote_user
        access_token.set_metadata(uri_datastore.resource.type, uri_spear.type.pvtaccesstoken)
        rs_wsdl_lxspear_notification = self.create_wsdl_resource('LxSpearNotification_2_2', uri_datastore, uri_spear)
        ds = DataStore()
        ds.put([rs_wsdl_lxspear_notification, client_cert, access_token])
        # lock is used to indicate when all the calls between tasks are complete
        # notice in task_1 callback method that it releases the lock
        # as this is the last call in the chain of calls between the tasks
        lock = threading.Lock()
        lock.acquire()     
                
        # stores the result of the notification call
        notification_result = Resource()
                    
        def cb_method_1(method, uri, res, result, context, **kwargs):
            notification_res = Resource()
            # set the notification checking interval
            notification_res.interval = 10
            # set the environment
            notification_res.environment = 'uat'
            notification_uri = context.put(uri_reference.notification.collection(True), notification_res)
            notification_result.notification_uri = notification_uri
            lock.release()

        # dummy task def resource
        task_def_resource = Resource()  
        
        # create other tasks required for test
        client_task = Task(self.spaces, uri_tasks.a, task_def_resource)
        client_task.cb_method_1 = cb_method_1      
        a2a_task = A2ATask(self.spaces, uri_tasks.eplanning.spear.a2atask, task_def_resource)
        a2a_task.log_level(LOGGING)        
        time_task = TimeTask(self.spaces, uri_tasks.base.service.timetask, task_def_resource)        
        # create timer task
        notification_task = NotificationTask(self.spaces, uri_tasks.eplanning.spear.notificationtask, task_def_resource)
        
        # start all the tasks         
        a2a_task.start()        
        time_task.start()
        notification_task.start()
        client_task.start()
        
        # wait while all the tasks initialise with the cb_start method
        time.sleep(3)
        
        # invoke the method_1 cb method on client task
        client_task.queue.put(('cb_method_1', None, None, None, None, None, {}))
        
        # lock until the callback is finished
        lock.acquire()
        
        # release other lock
        lock.release()
        
        # sleep for 30 seconds to see incoming notifications printed out to display
        time.sleep(65)
        
        # delete the notification monitor
        spaces_context.delete(notification_result.notification_uri)
        
        # sleep for 10 seconds to wait for the notification monitor to stop.
        time.sleep(10)
        
        # stop all the tasks
        a2a_task.task_stop()
        time_task.task_stop()
        notification_task.task_stop()
        client_task.task_stop()

    def create_wsdl_resource(self, wsdl_name, uri_datastore, uri_spear):
        wsdl_file = open(self.wsdl_path + wsdl_name +'.wsdl', 'rb')
        wsdl_string = wsdl_file.read()
        wsdl = WSDL(wsdl_string)
        rs_wsdl = Resource()
        rs_wsdl.element_dictionary = wsdl.element_dictionary
        rs_wsdl.set_metadata(uri_datastore.resource.type, uri_spear.type.wsdl)
        rs_wsdl.set_metadata(uri_spear.wsdl.name, wsdl_name)
        return rs_wsdl  
    
if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()